
import 'dart:convert';

import 'package:crypto/crypto.dart';

class GlobalSecryManager {
  static List<List<String>> constArray = [
    [
      "a",
      "b",
      "c",
      "d",
      "e",
      "f",
      "g",
      "h",
      "i",
      "j",
      "k",
      "l",
      "m",
      "n",
      "o",
      "p",
      "q",
      "r",
      "s",
      "t",
      "u",
      "v",
      "w",
      "s",
      "y",
      "z"
    ],
    [
      "A",
      "B",
      "C",
      "D",
      "E",
      "F",
      "G",
      "H",
      "I",
      "J",
      "K",
      "L",
      "M",
      "N",
      "O",
      "P",
      "Q",
      "R",
      "S",
      "T",
      "U",
      "V",
      "W",
      "S",
      "Y",
      "Z"
    ],
    ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
    ["!", "@", "#", "\$", "%", "^", "&", "*", "(", ")", "-", "+"]
  ];
  static List<int> positions = [0, 5, 13];

  static Future<String> generate(String domain, String password) async {
    List<int> bytes = const Utf8Codec().encoder.convert(domain + password);
    String hash = sha256.convert(bytes).toString(); //64位

    // 初始化4 * 4 的低位字符矩阵
    List<List<String>> lowCaseMatrix =
        List.generate(4, (_) => List.filled(4, "a"));
    extract(lowCaseMatrix, 0, 16, hash, constArray[0]);
    List<List<String>> upCaseMatrix =
        List.generate(4, (_) => List.filled(4, "A"));
    extract(upCaseMatrix, 16, 32, hash, constArray[1]);
    List<List<String>> numMatrix = List.generate(4, (_) => List.filled(4, "0"));
    extract(numMatrix, 32, 48, hash, constArray[2]);
    List<List<String>> symbolMatrix =
        List.generate(4, (_) => List.filled(4, "!"));
    extract(symbolMatrix, 48, 64, hash, constArray[3]);

    return position(lowCaseMatrix) +
        position(upCaseMatrix) +
        position(numMatrix) +
        position(symbolMatrix);
  }

  static void extract(List<List<String>> collection, int start, int end,
      String rawData, List<String> mapList) {
    for (int i = start; i < end; i++) {
      int code = rawData.codeUnitAt(i);
      String str = mapList[code % mapList.length];
      collection[(i - start) ~/ 4][(i % 4)] = str;
    }
    print(collection);
  }

  static String position(List<List<String>> collection) {
    String temp = "";
    for (var i = 0; i < 3; i++) {
      int y = positions[i] ~/ 4;
      int x = positions[i] % 4;
      temp += collection[y][x];
    }
    return temp;
  }
}